package org.qydjk.console.shiro;

import org.apache.shiro.session.Session;
import org.qydjk.common.redis.RedisClient;
import org.qydjk.common.util.SerializeUtil;

import java.io.Serializable;
import java.util.*;

/**
 * Session 管理
 */
public class JedisShiroSessionRepository {
    private RedisClient redisClient;
    //下面三个值只是事例
    private String sessionStatusName = "online_status";
    private String redisShiroSessionKeyPrefix = "shiro_session:";
    //key匹配
    private String redisShiroAllMachName =  "*shiro_session:*";

    public JedisShiroSessionRepository(RedisClient redisClient,String sessionStatusName,String redisShiroSessionKeyPrefix,String redisShiroAllMachName){
        this.redisClient = redisClient;
        this.sessionStatusName = sessionStatusName;
        this.redisShiroSessionKeyPrefix = redisShiroSessionKeyPrefix;
        this.redisShiroAllMachName = redisShiroAllMachName;
    }


    public void saveSession(Session session) {
        if (session == null || session.getId() == null)
            throw new NullPointerException("session is empty");
        try {
            byte[] key = SerializeUtil.serialize(buildRedisSessionKey(session.getId()));

            //不存在才添加。
            if(null == session.getAttribute(sessionStatusName)){
            	//Session 踢出自存存储。
            	ShiroSessionStatus sessionStatus = new ShiroSessionStatus();
            	session.setAttribute(sessionStatusName, sessionStatus);
            }

            byte[] value = SerializeUtil.serialize(session);

            /**
             * PS  : 注意： 这里我们配置 redis的TTL单位是秒，而【spring-shiro.xml】配置的是需要加3个0（毫秒）。
                long sessionTimeOut = session.getTimeout() / 1000;
                Long expireTime = sessionTimeOut + SESSION_VAL_TIME_SPAN + (5 * 60);
             */
             /*
            直接使用 (int) (session.getTimeout() / 1000) 的话，session失效和redis的TTL 同时生效
             */
            redisClient.set(key,value,(int) (session.getTimeout() / 1000));
        } catch (Exception e) {
        	e.printStackTrace();
        }
    }

    /**
     * 删除session
     * @param id
     */
    public void deleteSession(Serializable id) {
        if (id == null) {
            throw new NullPointerException("session id is empty");
        }
        try {
            redisClient.del(SerializeUtil.serialize(buildRedisSessionKey(id)));
        } catch (Exception e) {
        	e.printStackTrace();
        }
    }

    /**
     * 获取单个session
     * @param id
     * @return
     */
    public Session getSession(Serializable id) {
        if (id == null)
        	 throw new NullPointerException("session id is empty");
        Session session = null;
        try {
            byte[] value = redisClient.get(SerializeUtil.serialize(buildRedisSessionKey(id)));
            session = SerializeUtil.deserialize(value, Session.class);
        } catch (Exception e) {
        	e.printStackTrace();
        }
        return session;
    }

    /**
     * 模糊查询出所有的session
     * @return
     */
    public List<Session> getAllSessions() {
    	List<Session> sessions = new ArrayList<Session>();
        try {
            Set<byte[]> byteKeys = redisClient.keys(redisShiroAllMachName);
            if (byteKeys != null && byteKeys.size() > 0) {
                for (byte[] bs : byteKeys) {
                    Session obj = SerializeUtil.deserialize(redisClient.get(bs),
                            Session.class);
                    if(obj instanceof Session){
                        sessions.add(obj);
                    }
                }
            }
        } catch (Exception e) {
           e.printStackTrace();
        }
        return sessions;
    }

    private String buildRedisSessionKey(Serializable sessionId) {
        return redisShiroSessionKeyPrefix + sessionId;
    }
}
